<template>
  <div class="large-grid-container">
    <div ref="chartRef" class="chart-container"></div>
    <div class="controls">
      <button @click="toggleGrid" class="control-btn">
        {{ isGridVisible ? "隐藏网格" : "显示网格" }}
      </button>
      <button @click="toggleDensity" class="control-btn">
        {{ isHighDensity ? "降低密度" : "提高密度" }}
      </button>
      <div class="grid-settings">
        <label>中心点X: </label>
        <input
          type="number"
          v-model.number="centerX"
          step="10"
          @change="updateGrid"
        />
        <label>中心点Y: </label>
        <input
          type="number"
          v-model.number="centerY"
          step="10"
          @change="updateGrid"
        />
        <label>网格大小: </label>
        <input
          type="number"
          v-model.number="gridSize"
          step="1"
          min="1"
          @change="updateGrid"
        />
        <label>可见范围: </label>
        <input
          type="number"
          v-model.number="visibleRange"
          step="50"
          min="100"
          @change="updateGrid"
        />
      </div>
      <div class="info">
        <p>当前网格: {{ currentGridCount }}×{{ currentGridCount }}</p>
        <p>线宽: {{ lineWidth }}px</p>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted, onUnmounted, watch, nextTick, computed } from "vue";
import * as echarts from "echarts";

// 组件状态
const chartRef = ref(null);
const chart = ref(null);
const isGridVisible = ref(true);
const isHighDensity = ref(false); // 控制网格密度显示优化

// 网格配置
const centerX = ref(500); // 模拟经度中心
const centerY = ref(500); // 模拟纬度中心
const gridSize = ref(10); // 每个网格的大小
const visibleRange = ref(500); // 可见范围大小
const baseGridCount = 100; // 基础网格数量

// 计算当前实际显示的网格数量（根据缩放级别动态调整）
const currentGridCount = computed(() => {
  return isHighDensity.value ? baseGridCount : Math.floor(baseGridCount / 5);
});

// 线宽（高密度时自动减细线宽）
const lineWidth = computed(() => {
  return isHighDensity.value ? 0.5 : 1;
});

const gridLines = ref([]);
const isChartReady = ref(false);
const isDragging = ref(false); // 用于拖拽优化
const dragTimeout = ref(null);

// 初始化ECharts实例
onMounted(() => {
  nextTick(() => {
    if (chartRef.value) {
      // 初始化图表
      chart.value = echarts.init(chartRef.value);
      isChartReady.value = true;

      // 初始化配置
      initChart();

      // 绘制网格
      drawGrid();
    }
  });
});

// 初始化图表配置
const initChart = () => {
  if (!isChartReady.value) return;

  const option = {
    backgroundColor: "#f9f9f9",
    tooltip: {
      trigger: "item",
      formatter: function (params) {
        if (params.seriesType === "lines") {
          const [x, y] = params.data[0];
          return `坐标: (${x.toFixed(0)}, ${y.toFixed(0)})`;
        }
        return "";
      },
    },
    // 使用笛卡尔坐标系模拟地理坐标
    xAxis: {
      type: "value",
      min: centerX.value - visibleRange.value,
      max: centerX.value + visibleRange.value,
      show: true,
      axisLabel: {
        formatter: "{value}",
        fontSize: 10,
      },
    },
    yAxis: {
      type: "value",
      min: centerY.value - visibleRange.value,
      max: centerY.value + visibleRange.value,
      show: true,
      axisLabel: {
        formatter: "{value}",
        fontSize: 10,
      },
    },
    // 启用缩放和平移
    dataZoom: [
      {
        type: "inside",
        xAxisIndex: 0,
        filterMode: "none", // 不过滤数据，保持所有网格可见
        onZoomEnd: handleZoomOrPan,
        onMoveEnd: handleZoomOrPan,
      },
      {
        type: "inside",
        yAxisIndex: 0,
        filterMode: "none",
        onZoomEnd: handleZoomOrPan,
        onMoveEnd: handleZoomOrPan,
      },
    ],
    series: [],
  };

  chart.value.setOption(option);

  // 监听窗口大小变化
  window.addEventListener("resize", handleResize);
};

// 处理缩放和平移结束事件（优化性能）
const handleZoomOrPan = () => {
  if (isDragging.value) {
    clearTimeout(dragTimeout.value);
  } else {
    isDragging.value = true;
  }

  // 延迟重绘，避免拖动过程中频繁重绘
  dragTimeout.value = setTimeout(() => {
    drawGrid();
    isDragging.value = false;
  }, 300);
};

// 处理窗口大小变化
const handleResize = () => {
  if (isChartReady.value) {
    chart.value.resize();
  }
};

// 生成网格线数据
const generateGridData = () => {
  const lines = [];
  const halfRange = visibleRange.value;

  // 计算网格范围
  const minX = centerX.value - halfRange;
  const maxX = centerX.value + halfRange;
  const minY = centerY.value - halfRange;
  const maxY = centerY.value + halfRange;

  // 计算实际需要绘制的线条数量（基于当前视图范围）
  const xLinesCount = Math.min(
    currentGridCount.value,
    Math.ceil((maxX - minX) / gridSize.value)
  );
  const yLinesCount = Math.min(
    currentGridCount.value,
    Math.ceil((maxY - minY) / gridSize.value)
  );

  // 绘制水平线（Y固定）
  for (let i = 0; i <= xLinesCount; i++) {
    // 计算当前线的Y坐标
    const y = minY + (maxY - minY) * (i / xLinesCount);
    lines.push({
      type: "line",
      name: `水平线${i}`,
      lineStyle: {
        width: lineWidth.value,
        color:
          i % 10 === 0 ? "rgba(255, 0, 0, 0.8)" : "rgba(200, 200, 200, 0.5)",
        type: i % 10 === 0 ? "solid" : "dashed",
      },
      data: [
        [minX, y],
        [maxX, y],
      ],
    });
  }

  // 绘制垂直线（X固定）
  for (let i = 0; i <= yLinesCount; i++) {
    // 计算当前线的X坐标
    const x = minX + (maxX - minX) * (i / yLinesCount);
    lines.push({
      type: "line",
      name: `垂直线${i}`,
      lineStyle: {
        width: lineWidth.value,
        color:
          i % 10 === 0 ? "rgba(0, 0, 255, 0.8)" : "rgba(200, 200, 200, 0.5)",
        type: i % 10 === 0 ? "solid" : "dashed",
      },
      data: [
        [x, minY],
        [x, maxY],
      ],
    });
  }

  return lines;
};

// 绘制网格
const drawGrid = () => {
  if (!isChartReady.value || isDragging.value) return;

  gridLines.value = generateGridData();

  const option = chart.value.getOption();
  // 清除之前的网格线系列
  option.series = option.series.filter(
    (series) =>
      !series.name ||
      (!series.name.startsWith("水平线") && !series.name.startsWith("垂直线"))
  );

  // 添加新的网格线
  if (isGridVisible.value) {
    option.series = [...option.series, ...gridLines.value];
  }

  // 更新坐标轴范围
  option.xAxis[0].min = centerX.value - visibleRange.value;
  option.xAxis[0].max = centerX.value + visibleRange.value;
  option.yAxis[0].min = centerY.value - visibleRange.value;
  option.yAxis[0].max = centerY.value + visibleRange.value;

  // 使用nextTick确保在DOM更新后执行
  nextTick(() => {
    chart.value.setOption(option, true);
  });
};

// 切换网格显示状态
const toggleGrid = () => {
  isGridVisible.value = !isGridVisible.value;
  drawGrid();
};

// 切换网格密度
const toggleDensity = () => {
  isHighDensity.value = !isHighDensity.value;
  drawGrid();
};

// 更新网格
const updateGrid = () => {
  if (!isChartReady.value) return;

  nextTick(() => {
    drawGrid();
  });
};

// 监听容器大小变化
watch(
  () => chartRef.value?.clientWidth,
  () => {
    if (isChartReady.value) {
      chart.value.resize();
    }
  }
);

// 组件卸载时清理
onUnmounted(() => {
  window.removeEventListener("resize", handleResize);
  if (chart.value) {
    chart.value.dispose();
  }
  if (dragTimeout.value) {
    clearTimeout(dragTimeout.value);
  }
});
</script>

<style scoped>
.large-grid-container {
  position: relative;
  width: 100vw;
  height: 100vh;
  overflow: hidden;
}

.chart-container {
  width: 100%;
  height: 100%;
}

.controls {
  position: absolute;
  top: 20px;
  left: 20px;
  z-index: 10;
  background: rgba(255, 255, 255, 0.9);
  padding: 15px;
  border-radius: 8px;
  box-shadow: 0 2px 15px rgba(0, 0, 0, 0.1);
  max-width: 300px;
}

.control-btn {
  background: #42b983;
  color: white;
  border: none;
  padding: 8px 16px;
  border-radius: 4px;
  cursor: pointer;
  font-size: 14px;
  margin-bottom: 10px;
  transition: all 0.3s;
  width: 100%;
}

.control-btn:hover {
  background: #359e75;
  transform: translateY(-2px);
}

.grid-settings {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 15px 0;
}

.grid-settings label {
  font-size: 13px;
  color: #333;
  display: inline-block;
  width: 80px;
}

.grid-settings input {
  width: calc(100% - 90px);
  padding: 6px 8px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

.info {
  margin-top: 15px;
  padding-top: 10px;
  border-top: 1px dashed #eee;
  font-size: 12px;
  color: #666;
}

.info p {
  margin: 5px 0;
}
</style>
